class Container {
    static of(value) {
        return new Container(value)
    }

    constructor(value) {
        this._value = value
    }

    map(fn) {
        return Container.of(fn(this._value))
    }
}

class MayBe {
    static of(x) {
        return new MayBe(x)
    }

    isNothing() {
        return this._value === null || this._value === undefined
    }

    constructor(x) {
        this._value = x
    }

    map(fn) {
        return this.isNothing() ? this : MayBe.of(fn(this._value))
    }
}

const fp = require('loadsh/fp')

// 1、使用fp.add(x,y) 和 fp.map(f,x)创建一个能让functor里的值增加的函数ex1
let maybe = MayBe.of([5, 6, 1])

let ex1 = (x) => {
    let fn = fp.map(fp.add(x))
    return maybe.map(fn)
}
console.log(ex1(3))

// -----------------------------------------------------
// 2、实现ex2函数，能够使用fp.first获取表的第一个元素
let xs = Container.of(['do','ray','me','fa','so','la','ti','do'])

let ex2 = () => {
    return xs.map(fp.first)
}
console.log(ex2());

// -----------------------------------------------------
// 3、实现ex3函数，使用safeProp和fp.first找到user的名字的首字母
let safeProp = fp.curry(function(x, o) {
    return MayBe.of(o[x])
})
let user = { id:2, name: 'Albert' }
let ex3 = () => {
    let name = safeProp('name')(user)
    return name.map(fp.first)._value
}
console.log(ex3())

// -----------------------------------------------------
// 4、使用MayBe重写ex4，不要有if语句
let ex4 = function(n) {
    if (n) {
        return parseInt(n)
    }
}

let ex5 = function(n) {
    return MayBe.of(n).map(parseInt)._value
}
console.log(ex5());
